package com.bicap.cloud.nettyserver.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 服务端处理通道.这里只是打印一下请求的内容，并不对请求进行任何的响应 DiscardServerHandler 继承自
 * ChannelHandlerAdapter， 这个类实现了ChannelHandler接口， ChannelHandler提供了许多事件处理的接口方法，
 * 然后你可以覆盖这些方法。 现在仅仅只需要继承ChannelHandlerAdapter类而不是你自己去实现接口方法。
 *
 */
@Component
@ChannelHandler.Sharable
public class ServerDataHandler extends ChannelInboundHandlerAdapter {

    private Map<String,Channel> chanelMap = new ConcurrentHashMap<>();

    @Autowired
    private DataMessage dataMessage;

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        String ip = getIpAddr(ctx);
        chanelMap.put(ip,ctx.channel());
    }
    /**
     * 这里我们覆盖了chanelRead()事件处理方法。 每当从客户端收到新的数据时， 这个方法会在收到消息时被调用，
     * 这个例子中，收到的消息的类型是ByteBuf
     * 
     * @param ctx
     *            通道处理的上下文信息
     * @param msg
     *            接收的消息
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //收到任务发送到mq
        System.out.print(msg);
        Map map = JSON.parseObject((String)msg,Map.class);
        map.put("ipaddr",getIpAddr(ctx));
        String finalMsg = JSON.toJSONString(map, SerializerFeature.DisableCircularReferenceDetect);
        System.out.println("data::"+finalMsg);
//        dataMessage.sendOrder(finalMsg);

    }

    private String getIpAddr(ChannelHandlerContext ctx) {
        String address = ctx.channel().remoteAddress().toString();
        return address.substring(0,address.indexOf(":")).substring(1);
    }

    public Map<String, Channel> getChanelMap() {
        return chanelMap;
    }
    
    /***
     * 这个方法会在发生异常时触发
     * 
     * @param ctx
     * @param cause
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        /**
         * exceptionCaught() 事件处理方法是当出现 Throwable 对象才会被调用，即当 Netty 由于 IO
         * 错误或者处理器在处理事件时抛出的异常时。在大部分情况下，捕获的异常应该被记录下来 并且把关联的 channel
         * 给关闭掉。然而这个方法的处理方式会在遇到不同异常的情况下有不 同的实现，比如你可能想在关闭连接之前发送一个错误码的响应消息。
         */
        // 出现异常就关闭
        cause.printStackTrace();
        ctx.close();
    }
}
